/* eslint-disable no-param-reassign */
/* eslint-disable react/require-default-props */
import React, { useEffect, useMemo } from 'react';
import { observer } from 'mobx-react-lite';
import {
  DataSet, SelectBox, Select, TextField, Icon, Button, Tooltip,
} from 'choerodon-ui/pro';
import { NewTips } from '@choerodon/components';
import Record from 'choerodon-ui/pro/lib/data-set/Record';
import { omit, pick } from 'lodash';
import FormDs from './formDataSet';
import NewCodeFailedConditionsDs from './newCodeFailedConditionsDs';
import FullAmountCodeFailedConditionsDs from './fullAmountCodeFailedConditionsDs';
import './index.less';

interface IProps {
  onChange: (data: { [key: string]: any }) => void
  data?: { [key: string]: any }
  stepDataSet: DataSet
}

export interface IConditionItem {
  gatesMetric: string
  gatesOperator: string
  gatesValue: number
}

export interface IsonarQualityGateConditionVOListItem extends IConditionItem {
  gatesScope: string
  id?: string
}

export const transFormRecordDataToSubmitData = (data:
  {
    gatesEnable: boolean, gatesBlockAfterFail: boolean, newCodeFailedConditions?: IConditionItem[],
    fullAmountCodeFailedConditions?: IConditionItem[]
  }) => {
  let returnData: any = {};
  const {
    gatesEnable, gatesBlockAfterFail, newCodeFailedConditions,
    fullAmountCodeFailedConditions,
  } = data;
  if (!gatesEnable) {
    returnData = { gatesEnable: false };
  } else {
    returnData = {
      gatesEnable,
      gatesBlockAfterFail,
    };
    const sonarQualityGateConditionVOList: IsonarQualityGateConditionVOListItem[] = [];// 编辑时候加id
    newCodeFailedConditions?.forEach((item: IConditionItem & { gatesScope: string }) => {
      const obj = { ...item };
      obj.gatesScope = 'new';
      sonarQualityGateConditionVOList.push(obj);
    });
    fullAmountCodeFailedConditions?.forEach((item: IConditionItem & { gatesScope: string }) => {
      const obj = { ...item };
      obj.gatesScope = 'all';
      sonarQualityGateConditionVOList.push(obj);
    });
    returnData.sonarQualityGateConditionVOList = sonarQualityGateConditionVOList;
  }
  return {
    devopsCiSonarQualityGateVO: returnData,
  };
};

export const transFormSubmitDataToRecordData = (data: {
  gatesEnable: boolean, gatesBlockAfterFail?: boolean,
  sonarQualityGateConditionVOList?: IsonarQualityGateConditionVOListItem[]
}) => {
  const returnData: any = {};
  const newCodeFailedConditions: IConditionItem[] = [];
  const fullAmountCodeFailedConditions: IConditionItem[] = [];
  const gatesScopeMap = new Map([
    ['new', newCodeFailedConditions],
    ['all', fullAmountCodeFailedConditions],
  ]);

  const { gatesEnable, gatesBlockAfterFail, sonarQualityGateConditionVOList } = data;
  returnData.gatesEnable = gatesEnable;
  returnData.gatesBlockAfterFail = gatesBlockAfterFail;
  sonarQualityGateConditionVOList?.forEach((item) => {
    gatesScopeMap.get(item.gatesScope)!.push(pick(item, ['gatesMetric', 'gatesOperator', 'gatesValue']));
  });
  newCodeFailedConditions.length && Object.assign(returnData, {
    newCodeFailedConditions,
  });
  fullAmountCodeFailedConditions.length && Object.assign(returnData, {
    fullAmountCodeFailedConditions,
  });
  return {
    devopsCiSonarQualityGateVO: returnData,
  };
};

const Index: React.FC<IProps> = (props) => {
  const { onChange, data, stepDataSet } = props;
  const prefixCls = 'c7ncd-sonarqube-maven-qualityAccessControl';

  const formDs = useMemo(() => {
    const newCodeFailedConditionsDs = new DataSet(NewCodeFailedConditionsDs());
    const fullAmountCodeFailedConditionsDs = new DataSet(FullAmountCodeFailedConditionsDs());
    const ds = new DataSet(FormDs({
      newCodeFailedConditionsDs,
      fullAmountCodeFailedConditionsDs,
      stepDataSet,
    }));
    if (data) {
      ds.loadData([{
        gatesEnable: data.gatesEnable,
        gatesBlockAfterFail: data.gatesBlockAfterFail,
        newCodeFailedConditions: data.newCodeFailedConditions,
        fullAmountCodeFailedConditions: data.fullAmountCodeFailedConditions,
      }]);
    }
    return ds;
  }, []);

  useEffect(() => {
    async function syncFunc() {
      const formData = formDs?.current?.toData();
      onChange(omit(formData, '__dirty'));
      let validateResAll = true;
      const recordsAll = formDs?.children?.newCodeFailedConditions.records.concat(
        formDs?.children?.fullAmountCodeFailedConditions.records,
      );
      const res = recordsAll.map(async (item) => {
        if (!await item.validate(true)) {
          validateResAll = false;
        }
        return validateResAll;
      });
      await Promise.all(res);
      // SonarQube配置方式 变化时候也有设置
      stepDataSet?.setState('qualityAccessControlValidate', validateResAll);
    }
    syncFunc();
  }, [formDs?.current?.toData()]);

  const map = new Map([
    ['new', formDs.children.newCodeFailedConditions],
    ['fullAmount', formDs.children.fullAmountCodeFailedConditions],
  ]);

  const handleDsAdd = (type: 'new' | 'fullAmount') => {
    const currentDs = map.get(type);
    currentDs?.create();
  };

  const handleDsDelete = (type: 'new' | 'fullAmount', itemRecord: Record) => {
    const currentDs = map.get(type);
    currentDs?.delete(itemRecord, false);
  };

  const gatesEnableLabel = (
    <div className={`${prefixCls}-row-label`}>
      是否开启质量门禁
    </div>
  );

  const gatesBlockAfterFailLabel = (
    <div className={`${prefixCls}-row-label`}>
      质量门失败后是否阻塞
    </div>
  );

  const getDeleteVisible = () => {
    if (formDs?.children?.newCodeFailedConditions?.length
      + formDs?.children?.fullAmountCodeFailedConditions?.length === 1) {
      return false;
    }
    return true;
  };

  const getGatesMetricOption = (type:'new' | 'fullAmount', optionRecord:Record, currentRecord:Record) => {
    const ds = map.get(type);
    let disabled = false;
    ds!.forEach((dsRecord) => {
      if (dsRecord !== currentRecord) {
        if (dsRecord?.get('gatesMetric') === optionRecord.get('value')) {
          disabled = true;
          optionRecord.disabled = true;
        }
      }
    });
    return {
      disabled,
    };
  };

  const getGatesMetricOptionRenderer = (record:Record, text:string) => {
    if (record.disabled) {
      return <Tooltip title="该门禁项已被选择">{text}</Tooltip>;
    }
    return text;
  };

  return (
    <div className={prefixCls}>
      <h3>
        质量门禁
        <NewTips helpText="根据团队对代码质量的要求设置门禁阈值，帮助您立即了解代码质量是否合格。" />
      </h3>
      <SelectBox
        name="gatesEnable"
        label={gatesEnableLabel}
        dataSet={formDs}
      >
        <SelectBox.Option value>
          是
        </SelectBox.Option>
        <SelectBox.Option value={false}>
          否
        </SelectBox.Option>
      </SelectBox>
      {
        formDs?.current?.get('gatesEnable')
        && (
          <>
            <h4>
              质量门失败条件设置
            </h4>
            <div className={`${prefixCls}-row-condition`}>
              {
                formDs?.children?.newCodeFailedConditions?.map((itemRecord) => (
                  <div className={`${prefixCls}-row-condition-item`}>
                    <div className="ele-wrap">
                      <Select
                        name="gatesMetric"
                        record={itemRecord}
                        onOption={({ record }) => getGatesMetricOption('new', record, itemRecord)}
                        optionRenderer={({ record, text }:any) => getGatesMetricOptionRenderer(
                          record,
                          text,
                        )}
                      />
                    </div>
                    <div className="ele-wrap">
                      <Select name="gatesOperator" record={itemRecord} disabled />
                    </div>
                    <div className="ele-wrap">
                      <TextField name="gatesValue" record={itemRecord} />
                    </div>
                    {
                      getDeleteVisible() && <Button className="btn-delete" onClick={() => { handleDsDelete('new', itemRecord); }} icon="delete_black-o" funcType={'flat' as any} color={'primary' as any} />
                    }

                  </div>
                ))
              }
            </div>
            <div className={`${prefixCls}-row-add`}>
              <Button icon="add" funcType={'flat' as any} onClick={() => { handleDsAdd('new'); }}>添加新代码门禁条件</Button>
            </div>
            <div className={`${prefixCls}-row-condition`}>
              {
                formDs?.children?.fullAmountCodeFailedConditions?.map((itemRecord) => (
                  <div className={`${prefixCls}-row-condition-item`}>
                    <div className="ele-wrap">
                      <Select
                        name="gatesMetric"
                        record={itemRecord}
                        onOption={({ record }) => getGatesMetricOption('fullAmount', record, itemRecord)}
                        optionRenderer={({ record, text }:any) => getGatesMetricOptionRenderer(
                          record,
                          text,
                        )}
                      />
                    </div>
                    <div className="ele-wrap">
                      <Select name="gatesOperator" record={itemRecord} disabled />
                    </div>
                    <div className="ele-wrap">
                      <TextField name="gatesValue" record={itemRecord} />
                    </div>
                    {
                      getDeleteVisible() && <Button className="btn-delete" onClick={() => { handleDsDelete('fullAmount', itemRecord); }} icon="delete_black-o" funcType={'flat' as any} color={'primary' as any} />
                    }

                  </div>
                ))
              }
            </div>
            <div className={`${prefixCls}-row-add`}>
              <Button icon="add" funcType={'flat' as any} onClick={() => { handleDsAdd('fullAmount'); }}>添加全量代码门禁条件</Button>
            </div>
            <SelectBox name="gatesBlockAfterFail" label={gatesBlockAfterFailLabel} dataSet={formDs}>
              <SelectBox.Option value>
                是
              </SelectBox.Option>
              <SelectBox.Option value={false}>
                否
              </SelectBox.Option>
            </SelectBox>
          </>
        )
      }
    </div>
  );
};

export default observer(Index);
